home *** CD-ROM | disk | FTP | other *** search
/ BCI NET / BCI NET Dec 94.iso / archives / programming / source / dr2d.lha / modulesdr2dr.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-01-30  |  20.4 KB  |  953 lines

  1. #include "iffp/obj2d.h"
  2.  
  3. static int
  4.     NestLevel = 0;        /* Depth of the stack */
  5. static struct Obj2D
  6.     *ObjStack = 0;        /* Stack of objects for nested GRUPs */
  7.  
  8. /* Forward declarations */
  9. static struct Obj2D
  10.     *MakeObj( struct IFFhandle *, struct ContextNode * );
  11. static int
  12.     ReadPOLY( struct IFFhandle *, struct Obj2D * ),
  13.     ReadTPTH( struct IFFhandle *, struct Obj2D * ),
  14.     ReadSTXT( struct IFFhandle *, struct Obj2D * ),
  15.     ReadVBM( struct IFFhandle *, struct ContextNode *, struct Obj2D * ),
  16.     ReadDASH( struct IFFhandle *, struct Proj2D * ),
  17.     ReadLAYR( struct IFFhandle *, struct Proj2D * ),
  18.     ReadFONS( struct IFFhandle *, struct ContextNode *, struct Proj2D * ),
  19.     ReadCMAP( struct IFFhandle *, struct ContextNode *, struct Proj2D * ),
  20.     AddObj( struct Obj2D *, struct Proj2D * ),
  21.     DefineFill( struct Obj2D *, struct Proj2D * );
  22.  
  23. /* Data area for chunk reading */
  24. static union {
  25.     struct GRUPstruct
  26.     GRUPdata;
  27.     struct XTRNstruct
  28.     XTRNdata;
  29.     struct FILLstruct
  30.     FILLdata;
  31.     struct DASHstruct
  32.     DASHdata;
  33.     struct LAYRstruct
  34.     LAYRdata;
  35.     struct FONSstruct
  36.     FONSdata;
  37.     struct POLYstruct
  38.     POLYdata;
  39.     struct TPTHstruct
  40.     TPTHdata;
  41.     struct STXTstruct
  42.     STXTdata;
  43.     struct VBMstruct
  44.     VBMdata;
  45. }   Data;
  46.  
  47.  
  48.  
  49. int ReadDR2D( struct ParseInfo *PI, long GotForm, struct Proj2D **Conts )
  50. {
  51.     static long
  52.     ChunkList[] = {
  53.         ID_FORM, ID_DASH, ID_FILL, ID_LAYR,
  54.         ID_CMAP, ID_CMYK, ID_CNAM, ID_FONS,
  55.         ID_CPLY, ID_OPLY, ID_GRUP, ID_XTRN,
  56.         ID_TPTH, ID_STXT, ID_VBM,  0
  57.     },
  58.     DR2Dprops[] = {
  59.         ID_DR2D, ID_ATTR,
  60.         ID_DR2D, ID_BBOX,
  61.         ID_DR2D, ID_DRHD,
  62.         ID_DR2D, ID_PPRF
  63.     };
  64.     int
  65.     i, n,
  66.     NewNest = 0;
  67.     char
  68.     *s;
  69.     struct IFFHandle
  70.     *IFF;
  71.  
  72.     struct StoredProperty
  73.     *Drhd;
  74.     struct DRHDstruct
  75.     *DRHDdata;
  76.  
  77.     struct Proj2D
  78.     *Res;
  79.     long
  80.     Error;
  81.     struct ContextNode
  82.     *Chunk;
  83.     struct Obj2D
  84.     *Curr;            /* Current object */
  85.  
  86.  
  87.     Res = malloc( sizeof(struct Proj2D) );
  88.     if( !Res ) {
  89.     Error = IFFERR_NOMEM;
  90.     goto ErrorExit;
  91.     }
  92.  
  93.     /* Initialize the object environment */
  94.     Res->FontTable = 0;
  95.     Res->NumFont = Res->MaxFont = 0;
  96.     Res->DashCounts = 0;
  97.     Res->DashPatts = 0;
  98.     Res->NumDash = Res->MaxDash = 0;
  99.     Res->RGB_Table = 0;
  100.     Res->CMYK_Table = 0;
  101.     Res->CNAM_Table = 0;
  102.     Res->NumColor = 0;
  103.     Res->FillTable = 0;
  104.     Res->NumFills = Res->MaxFills = 0;
  105.     Res->LayerTable = 0;
  106.     Res->Objects = 0;
  107.     Res->LastObjs = 0;
  108.     Res->NumLayer = Res->MaxLayer = 0;
  109.  
  110.     /* Get the IFF handle */
  111.     IFF = PI->iff;
  112.  
  113.     /* Declare things we're interested in */
  114.     for( i = 0; ChunkList[i]; i++ ) {
  115.     Error = StopChunk( IFF, ID_DR2D, ChunkList[i] );
  116.     if( Error ) {
  117.         goto ErrorExit;
  118.     }
  119.     }
  120.  
  121.     Error = PropChunks( IFF, DR2Dprops, 4 );
  122.     if( Error ) {
  123.     goto ErrorExit;
  124.     }
  125.  
  126.     /* Tell IFFparse that we're interested in when the FORM terminates */
  127.     Error = StopOnExit( IFF, ID_DR2D, ID_FORM );
  128.     if( Error ) {
  129.     goto ErrorExit;
  130.     }
  131.  
  132.     NestLevel = GotForm != 0L;
  133.  
  134.     /* Actually read the file */
  135.     do {
  136.     Error = ParseIFF( IFF, IFFPARSE_SCAN );
  137.     switch( Error ) {
  138.     case 0 :
  139.         Chunk = CurrentChunk( IFF );
  140.  
  141.         switch( Chunk->cn_ID ) {
  142.         case ID_FORM :
  143.         if( NestLevel ) {
  144.             /* Nested FORM DR2D - must be GRUP, XTRN, or FILL */
  145.             NewNest = 1;
  146.         }
  147.         NestLevel++;
  148.             break;
  149.  
  150.         /* The following chunks must be the first in a nested FORM DR2D */
  151.         /* A FILL must not be nested inside any other chunk. */
  152.         case ID_FILL :
  153.         if( NestLevel > 2 ) {
  154.             Error = IFFERR_MANGLED;
  155.             goto ErrorExit;
  156.         }
  157.         /* FALLTHROUGH */
  158.         case ID_GRUP :
  159.         case ID_XTRN :
  160.         if( NestLevel < 2 || !NewNest ) {
  161.             Error = IFFERR_MANGLED;
  162.             goto ErrorExit;
  163.         }
  164.         NewNest = 0;
  165.  
  166.         Curr = MakeObj( IFF, Chunk );
  167.         if( !Curr ) {
  168.             Error = IFFERR_NOMEM;
  169.             goto ErrorExit;
  170.         }
  171.  
  172.         switch( Chunk->cn_ID ) {
  173.         case ID_FILL :
  174.             Error = ReadChunkRecords( IFF, &Data,
  175.                 sizeof(struct FILLstruct), 1 );
  176.             if( Error != 1 ) {
  177.             goto ErrorExit;
  178.             }
  179.  
  180.             /* This is a kludge; we're going to store
  181.              * the FILL ID in the GRUP.NumObjs and the
  182.              * fill object in the GRUP.Objs
  183.              */
  184.             Curr->Data.GRUPdata.NumObjs = Data.FILLdata.FillID;
  185.             break;
  186.  
  187.         case ID_GRUP :
  188.             Error = ReadChunkRecords( IFF, &Data,
  189.                 sizeof(struct GRUPstruct), 1 );
  190.             if( Error != 1 ) {
  191.             goto ErrorExit;
  192.             }
  193.             Curr->Data.GRUPdata.NumObjs = Data.GRUPdata.NumObjs;
  194.             Curr->Data.GRUPdata.Tail = 0;
  195.             break;
  196.  
  197.         case ID_XTRN :
  198.             Error = ReadChunkRecords( IFF, &Data,
  199.                 sizeof(struct XTRNstruct), 1 );
  200.             if( Error != 1 ) {
  201.             goto ErrorExit;
  202.             }
  203.  
  204.             Curr->Data.XTRNdata.ApplCallBacks =
  205.                 Data.XTRNdata.ApplCallBacks;
  206.             Curr->Data.XTRNdata.ApplNameLength = n =
  207.                 Data.XTRNdata.ApplNameLength;
  208.  
  209.             Curr->Data.XTRNdata.ApplName = s = malloc( n );
  210.             if( !s ) {
  211.             Error = IFFERR_NOMEM;
  212.             goto ErrorExit;
  213.             }
  214.  
  215.             Error = ReadChunkRecords( IFF, s, n, 1 );
  216.             if( Error != 1 ) {
  217.             goto ErrorExit;
  218.             }
  219.             break;
  220.         }
  221.  
  222.         /* Stack the context we need */
  223.         Curr->Next = ObjStack;
  224.         ObjStack = Curr;
  225.         break;
  226.  
  227.         /* The following chunks must not be in a nested FORM DR2D */
  228.         case ID_DASH :
  229.         if( NestLevel > 1 ) {
  230.             Error = IFFERR_MANGLED;
  231.             goto ErrorExit;
  232.         }
  233.  
  234.         Error = ReadDASH( IFF, Res );
  235.         if( Error != 0 )    goto ErrorExit;
  236.  
  237.         break;
  238.  
  239.         case ID_LAYR :
  240.         if( NestLevel > 1 ) {
  241.             Error = IFFERR_MANGLED;
  242.             goto ErrorExit;
  243.         }
  244.  
  245.         Error = ReadLAYR( IFF, Res );
  246.         if( Error != 0 )    goto ErrorExit;
  247.  
  248.         break;
  249.  
  250.         case ID_CMAP :
  251.         if( NestLevel > 1 ) {
  252.             Error = IFFERR_MANGLED;
  253.             goto ErrorExit;
  254.         }
  255.  
  256.         Error = ReadCMAP( IFF, Chunk, Res );
  257.         if( Error != 0 )    goto ErrorExit;
  258.  
  259.         break;
  260.  
  261.         case ID_CMYK :
  262.         if( NestLevel > 1 ) {
  263.             Error = IFFERR_MANGLED;
  264.             goto ErrorExit;
  265.         }
  266.         /* TBD */
  267.         break;
  268.  
  269.         case ID_CNAM :
  270.         if( NestLevel > 1 ) {
  271.             Error = IFFERR_MANGLED;
  272.             goto ErrorExit;
  273.         }
  274.         /* TBD */
  275.         break;
  276.  
  277.         case ID_FONS :
  278.         if( NestLevel > 1 ) {
  279.             Error = IFFERR_MANGLED;
  280.             goto ErrorExit;
  281.         }
  282.  
  283.         Error = ReadFONS( IFF, Chunk, Res );
  284.         if( Error != 0 )    goto ErrorExit;
  285.  
  286.         break;
  287.  
  288.         /* The following chunks can occur anywhere */
  289.         case ID_CPLY :
  290.         case ID_OPLY :
  291.         case ID_TPTH :
  292.         case ID_STXT :
  293.         case ID_VBM :
  294.         if( NewNest ) {
  295.             Error = IFFERR_MANGLED;
  296.             goto ErrorExit;
  297.         }
  298.  
  299.         Curr = MakeObj( IFF, Chunk );
  300.         if( !Curr ) {
  301.             Error = IFFERR_NOMEM;
  302.             goto ErrorExit;
  303.         }
  304.  
  305.         /* Read the object specific data */
  306.         switch( Curr->Type ) {
  307.         case ID_CPLY :
  308.         case ID_OPLY :
  309.             Error = ReadPOLY( IFF, Curr );
  310.             if( Error != 0 )    goto ErrorExit;
  311.             break;
  312.  
  313.         case ID_TPTH :
  314.             Error = ReadTPTH( IFF, Curr );
  315.             if( Error != 0 )    goto ErrorExit;
  316.  
  317.             break;
  318.  
  319.         case ID_STXT :
  320.             Error = ReadSTXT( IFF, Curr );
  321.             if( Error != 0 )    goto ErrorExit;
  322.             break;
  323.  
  324.         case ID_VBM :
  325.             Error = ReadVBM( IFF, Chunk, Curr );
  326.             if( Error != 0 )    goto ErrorExit;
  327.             break;
  328.         }
  329.  
  330.         /* Put the object in the correct place */
  331.         Error = AddObj( Curr, Res );
  332.         if( Error != 0 )    goto ErrorExit;
  333.  
  334.         break;
  335.  
  336.         /* This should never happen */
  337.         default :
  338.         Error = IFFERR_MANGLED;
  339.         goto ErrorExit;
  340.  
  341.         }
  342.         break;
  343.  
  344.     case IFFERR_EOC :
  345.         /* Leaving FORM DR2D */
  346.  
  347.         /* Pop the stack */
  348.         Curr = ObjStack;
  349.         if( ObjStack )    ObjStack = ObjStack->Next;
  350.  
  351.         NestLevel--;
  352.  
  353.         if( !Curr )     break;
  354.  
  355.         if( Curr->Type == ID_FILL ) {
  356.         /* Define the fill */
  357.         Error = DefineFill( Curr, Res );
  358.         if( Error != 0 )    goto ErrorExit;
  359.  
  360.         }
  361.         else {
  362.         Error = AddObj( Curr, Res );
  363.         if( Error != 0 )    goto ErrorExit;
  364.         }
  365.         break;
  366.  
  367.     default :
  368.         /* Error reading the file */
  369.         goto ErrorExit;
  370.     }
  371.     } while( NestLevel );
  372.  
  373.     /* Get the final attributes */
  374.     Drhd = FindProp( IFF, ID_DR2D, ID_DRHD );
  375.     if( !Drhd ) {
  376.     Error = IFFERR_MANGLED;
  377.     goto ErrorExit;
  378.     }
  379.     DRHDdata = (struct DRHDstruct *)Drhd->sp_Data;
  380.     ieee2flt( &DRHDdata->UL_X, &Res->UL_X );
  381.     ieee2flt( &DRHDdata->UL_Y, &Res->UL_Y );
  382.     ieee2flt( &DRHDdata->LR_X, &Res->LR_X );
  383.     ieee2flt( &DRHDdata->LR_Y, &Res->LR_Y );
  384.  
  385.     *Conts = Res;
  386.     return 0;
  387.  
  388.     /************* Error exit *****************/
  389. ErrorExit :
  390.     if( Res )            free( Res );
  391.  
  392.     *Conts = 0;
  393.     return Error;
  394. }
  395.  
  396.  
  397. static struct Obj2D *MakeObj(    struct IFFhandle *IFF,
  398.                 struct ContextNode *Chunk    )
  399. {
  400.     struct Obj2D
  401.     *Res;
  402.     struct StoredProperty
  403.     *Bbox,
  404.     *Attr;
  405.     struct BBOXstruct
  406.     *BBOXdata;
  407.  
  408.     Res = malloc( sizeof( struct Obj2D ) );
  409.     if( !Res ) {
  410.     return 0;
  411.     }
  412.  
  413.     Res->Type = Chunk->cn_ID;
  414.  
  415.     Bbox = FindProp( IFF, ID_DR2D, ID_BBOX );
  416.     if( Bbox ) {
  417.     BBOXdata = (struct BBOXstruct *)Bbox->sp_Data;
  418.     ieee2flt( &BBOXdata->XMin, &Res->XMin );
  419.     ieee2flt( &BBOXdata->YMin, &Res->YMin );
  420.     ieee2flt( &BBOXdata->XMax, &Res->XMax );
  421.     ieee2flt( &BBOXdata->YMax, &Res->YMax );
  422.     }
  423.     else {
  424.     Res->XMin = Res->YMin = Res->XMax = Res->YMax = 0;
  425.     }
  426.  
  427.     Attr = FindProp( IFF, ID_DR2D, ID_ATTR );
  428.     if( Attr ) {
  429.     Res->Attrs = *(struct ATTRstruct *)Attr->sp_Data;
  430.     ieee2flt( &Res->Attrs.EdgeThick, &Res->Attrs.EdgeThick );
  431.     }
  432.     else {
  433.     Res->Attrs.FillType = FT_NONE;
  434.     Res->Attrs.JoinType = JT_NONE;
  435.     Res->Attrs.EdgePattern = 0;
  436.     Res->Attrs.ArrowHeads = 0;
  437.     Res->Attrs.FillValue = 0;
  438.     Res->Attrs.EdgeValue = 0;
  439.     Res->Attrs.WhichLayer = 0;
  440.     Res->Attrs.EdgeThick = 0;    /* 0 must always be 0! */
  441.     }
  442.  
  443.     Res->Next = 0;
  444.  
  445.     return Res;
  446. }
  447.  
  448.  
  449. static int ReadPOLY( struct IFFhandle *IFF, struct Obj2D *Obj )
  450. {
  451.     int
  452.     i, n,
  453.     Error;
  454.     Coord
  455.     *Pts;
  456.     
  457.     Error = ReadChunkRecords( IFF, &Data,
  458.                 sizeof(struct POLYstruct), 1 );
  459.     if( Error != 1 ) {
  460.     return Error;
  461.     }
  462.     Obj->Data.POLYdata.NumPoints = n = Data.POLYdata.NumPoints;
  463.  
  464.     Obj->Data.POLYdata.Coords = Pts = malloc( n * 2 * sizeof(Coord) );
  465.     if( !Pts ) {
  466.     return IFFERR_NOMEM;
  467.     }
  468.  
  469.     Error = ReadChunkRecords( IFF, Pts, n*2*sizeof(Coord), 1 );
  470.     if( Error != 1 ) {
  471.     return Error;
  472.     }
  473.  
  474.     /* Convert from IEEE to internal form */
  475.     for( i = 0; i < n; i++ ) {
  476.     if( ((long *)Pts)[2*i] == DR2D_IND ) {
  477.         ((long *)Pts)[2*i] = FLT_IND;
  478.     }
  479.     else {
  480.         ieee2flt( (long *)Pts + 2*i, Pts + 2*i );
  481.         ieee2flt( (long *)Pts + 2*i + 1, Pts + 2*i + 1 );
  482.     }
  483.     }
  484.     return 0;
  485. }
  486.  
  487.  
  488. static int ReadTPTH( struct IFFhandle *IFF, struct Obj2D *Obj )
  489. {
  490.     int
  491.     i, n,
  492.     Error;
  493.     char
  494.     c, *s;
  495.     Coord
  496.     *Pts;
  497.  
  498.     /* Read TPTH information */
  499.     Error = ReadChunkRecords( IFF, &Data, sizeof(struct TPTHstruct), 1 );
  500.     if( Error != 1 ) {
  501.     return Error;
  502.     }
  503.  
  504.     /* Read text string */
  505.     Obj->Data.TPTHdata.WhichFont = Data.TPTHdata.WhichFont;
  506.     Obj->Data.TPTHdata.NumChars = n = Data.TPTHdata.NumChars;
  507.     Obj->Data.TPTHdata.String = s = malloc( n );
  508.     if( !s ) {
  509.     return IFFERR_NOMEM;
  510.     }
  511.     Error = ReadChunkRecords( IFF, s, n, 1 );
  512.     if( Error != 1 ) {
  513.     return Error;
  514.     }
  515.     /* Read pad byte, if needed */
  516.     if( n & 1 ) {
  517.     Error = ReadChunkRecords( IFF, &c, 1, 1 );
  518.     if( Error != 1 )    return Error;
  519.     }
  520.  
  521.  
  522.     /* Read text path */
  523.     Obj->Data.TPTHdata.NumPath = n = Data.TPTHdata.NumPoints;
  524.     Obj->Data.TPTHdata.Path = Pts = malloc( n * 2 * sizeof(Coord) );
  525.     if( !Pts ) {
  526.     return IFFERR_NOMEM;
  527.     }
  528.     Error = ReadChunkRecords( IFF, Pts, n*2*sizeof(Coord), 1 );
  529.     if( Error != 1 ) {
  530.     return Error;
  531.     }
  532.  
  533.     /* Convert from IEEE to internal form */
  534.     ieee2flt( &Data.TPTHdata.CharW, &Obj->Data.TPTHdata.Width );
  535.     ieee2flt( &Data.TPTHdata.CharH, &Obj->Data.TPTHdata.Height );
  536.  
  537.     for( i = 0; i < n; i++ ) {
  538.     if( ((long *)Pts)[2*i] == DR2D_IND ) {
  539.         ((long *)Pts)[2*i] = FLT_IND;
  540.     }
  541.     else {
  542.         ieee2flt( (long *)Pts + 2*i, Pts + 2*i );
  543.         ieee2flt( (long *)Pts + 2*i + 1, Pts + 2*i + 1 );
  544.     }
  545.     }
  546.     return 0;
  547. }
  548.  
  549.  
  550. static int ReadSTXT( struct IFFhandle *IFF, struct Obj2D *Obj )
  551. {
  552.     int
  553.     n,
  554.     Error;
  555.     char
  556.     *s;
  557.  
  558.     /* Read STXT information */
  559.     Error = ReadChunkRecords( IFF, &Data, sizeof(struct STXTstruct), 1 );
  560.     if( Error != 1 ) {
  561.     return Error;
  562.     }
  563.  
  564.     /* Read text string */
  565.     Obj->Data.STXTdata.WhichFont = Data.STXTdata.WhichFont;
  566.     Obj->Data.STXTdata.NumChars = n = Data.STXTdata.NumChars;
  567.     Obj->Data.STXTdata.String = s = malloc( n );
  568.     if( !s ) {
  569.     return IFFERR_NOMEM;
  570.     }
  571.     Error = ReadChunkRecords( IFF, s, n, 1 );
  572.     if( Error != 1 ) {
  573.     return Error;
  574.     }
  575.  
  576.     /* Convert from IEEE to internal form */
  577.     ieee2flt( &Data.STXTdata.CharW, &Obj->Data.STXTdata.Width );
  578.     ieee2flt( &Data.STXTdata.CharH, &Obj->Data.STXTdata.Height );
  579.     ieee2flt( &Data.STXTdata.BaseX, &Obj->Data.STXTdata.XPos );
  580.     ieee2flt( &Data.STXTdata.BaseY, &Obj->Data.STXTdata.YPos );
  581.     ieee2flt( &Data.STXTdata.Rotation, &Obj->Data.STXTdata.Rotation );
  582.  
  583.     return 0;
  584. }
  585.  
  586.  
  587. static int ReadVBM(    struct IFFhandle *IFF,
  588.             struct ContextNode *Chunk,
  589.             struct Obj2D *Obj    )
  590. {
  591.     int
  592.     n, Bytes,
  593.     Error;
  594.     char
  595.     *s;
  596.  
  597.     /* Read VBM information */
  598.     Error = ReadChunkRecords( IFF, &Data, sizeof(struct VBMstruct), 1 );
  599.     if( Error != 1 ) {
  600.     return Error;
  601.     }
  602.  
  603.     /* Kludge to get around ProVector 2.0 erroneous writing of VBM chunks */
  604.     n = Bytes = Data.VBMdata.PathLen;
  605.     if( (Chunk->cn_Size - Chunk->cn_Scan) < n ) {
  606.     Bytes = Chunk->cn_Size - Chunk->cn_Scan;
  607.     }
  608.  
  609.     /* Read path to bitmap */
  610.     Obj->Data.VBMdata.PathLen = n;
  611.     Obj->Data.VBMdata.Path = s = malloc( n );
  612.     if( !s ) {
  613.     return IFFERR_NOMEM;
  614.     }
  615.  
  616.     Error = ReadChunkRecords( IFF, s, Bytes, 1 );
  617.     if( Error != 1 ) {
  618.     return Error;
  619.     }
  620.  
  621.     /* Make sure string is null terminated; gets around PV2.0 bug */
  622.     s[n-1] = 0;
  623.  
  624.     /* Convert from IEEE to internal form */
  625.     ieee2flt( &Data.VBMdata.XPos, &Obj->Data.VBMdata.XPos );
  626.     ieee2flt( &Data.VBMdata.YPos, &Obj->Data.VBMdata.YPos );
  627.     ieee2flt( &Data.VBMdata.XSize, &Obj->Data.VBMdata.Width );
  628.     ieee2flt( &Data.VBMdata.YSize, &Obj->Data.VBMdata.Height );
  629.     ieee2flt( &Data.VBMdata.Rotation, &Obj->Data.VBMdata.Rotation );
  630.  
  631.     return 0;
  632. }
  633.  
  634.  
  635.  
  636. static int ReadDASH( struct IFFhandle *IFF, struct Proj2D *Conts )
  637. {
  638.     int
  639.     i, n, m,
  640.     Error;
  641.     Coord
  642.     *Pts;
  643.  
  644.     Error = ReadChunkRecords( IFF, &Data, sizeof(struct DASHstruct), 1 );
  645.     if( Error != 1 ) {
  646.     return Error;
  647.     }
  648.  
  649.     n = Data.DASHdata.DashID;
  650.     if( n >= Conts->MaxDash ) {
  651.     /* Extend the dash table */
  652.     if( Conts->MaxDash ) {
  653.         Conts->MaxDash *= 2;
  654.         m = Conts->MaxDash;
  655.         Conts->DashCounts = realloc( Conts->DashCounts, m * sizeof(int) );
  656.         Conts->DashPatts = realloc( Conts->DashPatts, m * sizeof(Coord *) );
  657.     }
  658.     else {
  659.         Conts->MaxDash = m = 2;
  660.         Conts->DashCounts = malloc( m * sizeof(int) );
  661.         Conts->DashPatts = malloc( m * sizeof(Coord *) );
  662.     }
  663.  
  664.     if( !Conts->DashCounts || !Conts->DashPatts ) {
  665.         return IFFERR_NOMEM;
  666.     }
  667.  
  668.     /* Initialize the dash lists */
  669.     for( i = Conts->NumDash; i < m; i++ ) {
  670.         Conts->DashCounts[i] = 0;
  671.         Conts->DashPatts[i] = 0;
  672.     }
  673.     }
  674.  
  675.     if( n >= Conts->NumDash ) {
  676.     Conts->NumDash = n + 1;
  677.     }
  678.  
  679.     /* Read the dash pattern */
  680.     Conts->DashCounts[n] = i = Data.DASHdata.NumDashes;
  681.  
  682.     if( i ) {
  683.     /* Note that a count of 0 is possible here! */
  684.     Conts->DashPatts[n] = Pts = malloc( i * sizeof(Coord) );
  685.     if( !Pts ) {
  686.         return IFFERR_NOMEM;
  687.     }
  688.     Error = ReadChunkRecords( IFF, Pts, i * sizeof(Coord), 1 );
  689.     if( Error != 1 ) {
  690.         return Error;
  691.     }
  692.  
  693.     /* Convert to internal numeric rep */
  694.     for( i--; i >= 0; i-- ) {
  695.         ieee2flt( Pts + i, Pts + i );
  696.     }
  697.     }
  698.  
  699.     return 0;
  700. }
  701.  
  702.  
  703.  
  704. static int ReadLAYR( struct IFFhandle *IFF, struct Proj2D *Conts )
  705. {
  706.     int
  707.     i, n, m,
  708.     Error;
  709.  
  710.     Error = ReadChunkRecords( IFF, &Data, sizeof(struct LAYRstruct), 1 );
  711.     if( Error != 1 ) {
  712.     return Error;
  713.     }
  714.  
  715.     n = Data.LAYRdata.LayerID;
  716.     if( n >= Conts->MaxLayer ) {
  717.     /* Extend the layer table */
  718.     if( Conts->MaxLayer ) {
  719.         Conts->MaxLayer *= 2;
  720.         m = Conts->MaxLayer;
  721.         Conts->LayerTable = realloc( Conts->LayerTable,
  722.                     m * sizeof(struct LAYRstruct) );
  723.         Conts->Objects = realloc( Conts->Objects,
  724.                     m * sizeof(struct Obj2D *) );
  725.         Conts->LastObjs = realloc( Conts->LastObjs,
  726.                     m * sizeof(struct Obj2D *) );
  727.     }
  728.     else {
  729.         Conts->MaxLayer = m = 2;
  730.         Conts->LayerTable = malloc( m * sizeof(struct LAYRstruct) );
  731.         Conts->Objects = malloc( m * sizeof(struct Obj2D *) );
  732.         Conts->LastObjs = malloc( m * sizeof(struct Obj2D *) );
  733.     }
  734.  
  735.     if( !Conts->LayerTable || !Conts->Objects || !Conts->LastObjs ) {
  736.         return IFFERR_NOMEM;
  737.     }
  738.  
  739.     /* Initialize the layer lists */
  740.     for( i = Conts->NumLayer; i < m; i++ ) {
  741.         Conts->Objects[i] = 0;
  742.         Conts->LastObjs[i] = 0;
  743.         Conts->LayerTable[i].LayerID = i;
  744.         Conts->LayerTable[i].LayerName[0] = 0;
  745.         Conts->LayerTable[i].Flags = 0;
  746.         Conts->LayerTable[i].Pad0 = 0;
  747.     }
  748.     }
  749.  
  750.     if( n >= Conts->NumLayer ) {
  751.     Conts->NumLayer = n + 1;
  752.     }
  753.  
  754.     /* Copy the pertinent data */
  755.     Conts->LayerTable[n] = Data.LAYRdata;
  756.  
  757.     return 0;
  758. }
  759.  
  760.  
  761. static int ReadFONS(    struct IFFhandle *IFF,
  762.             struct ContextNode *Chunk,
  763.             struct Proj2D *Conts    )
  764. {
  765.     int
  766.     i, n, m,
  767.     Error;
  768.  
  769.     Error = ReadChunkRecords( IFF, &Data, sizeof(struct FONSstruct), 1 );
  770.     if( Error != 1 ) {
  771.     return Error;
  772.     }
  773.  
  774.     n = Data.FONSdata.FontID;
  775.  
  776.     if( n >= Conts->MaxFont ) {
  777.     /* Extend the layer table */
  778.     if( Conts->MaxFont ) {
  779.         Conts->MaxFont *= 2;
  780.         m = Conts->MaxFont;
  781.         Conts->FontTable = realloc( Conts->FontTable,
  782.                     m * sizeof(struct FONSstruct) );
  783.         Conts->FontNames = realloc( Conts->FontNames,
  784.                     m * sizeof(char *) );
  785.     }
  786.     else {
  787.         Conts->MaxFont = m = 2;
  788.         Conts->FontTable = malloc( m * sizeof(struct FONSstruct) );
  789.         Conts->FontNames = malloc( m * sizeof(char *) );
  790.     }
  791.  
  792.     if( !Conts->FontTable || !Conts->FontNames ) {
  793.         return IFFERR_NOMEM;
  794.     }
  795.  
  796.     /* Initialize the font table */
  797.     for( i = Conts->NumLayer; i < m; i++ ) {
  798.         Conts->FontTable[i].FontID = 0;
  799.         Conts->FontTable[i].Pad1 = 0;
  800.         Conts->FontTable[i].Proportional = 0;
  801.         Conts->FontTable[i].Serif = 0;
  802.         Conts->FontNames[i] = 0;
  803.     }
  804.     }
  805.  
  806.     if( Conts->NumFont >= n ) {
  807.     Conts->NumFont = n + 1;
  808.     }
  809.  
  810.     /* Read the font name */
  811.     m = Chunk->cn_Size - Chunk->cn_Scan;
  812.     Conts->FontTable[n] = Data.FONSdata;
  813.     Conts->FontNames[n] = malloc( m );
  814.     if( !Conts->FontNames[n] ) {
  815.     return IFFERR_NOMEM;
  816.     }
  817.  
  818.     Error = ReadChunkRecords( IFF, Conts->FontNames[n], m, 1 );
  819.     if( Error != 1 ) {
  820.     return Error;
  821.     }
  822.  
  823.     return 0;
  824. }
  825.  
  826.  
  827. static int ReadCMAP(    struct IFFhandle *IFF,
  828.             struct ContextNode *Chunk,
  829.             struct Proj2D *Conts    )
  830. {
  831.     int
  832.     i, n,
  833.     Error;
  834.  
  835.     /* Allocate tables */
  836.     Conts->NumColor = n = Chunk->cn_Size / 3;
  837.     Conts->RGB_Table = malloc( n * 3 );
  838.     Conts->CMYK_Table = malloc( n * 4 );
  839.     Conts->CNAM_Table = malloc( n * sizeof(char *) );
  840.  
  841.     if( !Conts->RGB_Table || !Conts->CMYK_Table || !Conts->CNAM_Table ) {
  842.     return IFFERR_NOMEM;
  843.     }
  844.  
  845.     /* Read the RGB data */
  846.     Error = ReadChunkRecords( IFF, Conts->RGB_Table, n * 3, 1 );
  847.     if( Error != 1 ) {
  848.     return Error;
  849.     }
  850.  
  851.     /* Initialize the CMYK and CNAM tables */
  852.     for( i = 0; i < n; i++ ) {
  853.     Conts->CMYK_Table[4*i  ] = 255 - Conts->RGB_Table[3*i  ];
  854.     Conts->CMYK_Table[4*i+1] = 255 - Conts->RGB_Table[3*i+1];
  855.     Conts->CMYK_Table[4*i+2] = 255 - Conts->RGB_Table[3*i+2];
  856.     Conts->CMYK_Table[4*i+3] = 0;
  857.     Conts->CNAM_Table[i] = 0;
  858.     }
  859.  
  860.     return 0;
  861. }
  862.  
  863.  
  864.  
  865. static int AddObj( struct Obj2D *Obj, struct Proj2D *Conts )
  866. {
  867.     int
  868.     n;
  869.  
  870.     Obj->Next = 0;
  871.  
  872.     if( NestLevel > 1 ) {
  873.     /* Add the current object to a group, etc. */
  874.     switch( ObjStack->Type ) {
  875.     case ID_GRUP :
  876.         if( ObjStack->Data.GRUPdata.Tail ) {
  877.         ObjStack->Data.GRUPdata.Tail->Next = Obj;
  878.         }
  879.         else {
  880.         ObjStack->Data.GRUPdata.Objs = Obj;
  881.         }
  882.         ObjStack->Data.GRUPdata.Tail = Obj;
  883.         break;
  884.     case ID_FILL :
  885.         ObjStack->Data.GRUPdata.Objs = Obj;
  886.         break;
  887.     case ID_XTRN :
  888.         ObjStack->Data.XTRNdata.Obj = Obj;
  889.         break;
  890.     }
  891.     }
  892.     else {
  893.     /* Add it to the object table */
  894.     n = Obj->Attrs.WhichLayer;
  895.     if( n >= Conts->NumLayer ) {
  896.         return IFFERR_MANGLED;
  897.     }
  898.     if( Conts->LastObjs[n] ) {
  899.         Conts->LastObjs[n]->Next = Obj;
  900.     }
  901.     else {
  902.         Conts->Objects[n] = Obj;
  903.     }
  904.     Conts->LastObjs[n] = Obj;
  905.     }
  906.  
  907.     return 0;
  908. }
  909.  
  910.  
  911. static int DefineFill( struct Obj2D *Obj, struct Proj2D *Conts )
  912. {
  913.     int
  914.     i, n, m;
  915.  
  916.     n = Obj->Data.GRUPdata.NumObjs;
  917.  
  918.     if( n >= Conts->MaxFills ) {
  919.     /* Extend the fill table */
  920.     if( Conts->MaxFills ) {
  921.         Conts->MaxFills *= 2;
  922.         m = Conts->MaxFills;
  923.         Conts->FillTable = realloc( Conts->FillTable, m * sizeof(struct Obj2D *) );
  924.     }
  925.     else {
  926.         Conts->MaxFills = m = 2;
  927.         Conts->FillTable = malloc( m * sizeof(struct Obj2D *) );
  928.     }
  929.     if( !Conts->FillTable ) {
  930.         return IFFERR_NOMEM;
  931.     }
  932.  
  933.     for( i = Conts->NumFills; i < m; i++ ) {
  934.         Conts->FillTable[i] = 0;
  935.     }
  936.     }
  937.  
  938.     if( Conts->NumFills >= n ) {
  939.     Conts->NumFills = n + 1;
  940.     }
  941.  
  942.     /* Save the fill pattern */
  943.     Conts->FillTable[n] = Obj->Data.GRUPdata.Objs;
  944.  
  945.     /* Free this dummy object */
  946.     free( Obj );
  947.  
  948.     return 0;
  949. }
  950.  
  951.  
  952. /*** EOF dr2dr.c ***/
  953.